;Adam Wilford
;Lab 4

#include <p16F887.inc>
	__CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
	__CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

     cblock     0x20
Display              ; define a variable to hold the diplay
Display1             ;used for LED[0] bit inversion
Delay1               ;used for the 15 countdown with Timer0
     endc


     cblock 0x70     ; located in RAM
W_Save               ;used to save the W register on interrupt
STATUS_Save          ;used to save the state of the STATUS register on interrupt
     endc

     org 0          ;statt of the primary program loop
     goto      Start ;goto the start of the main loop

     org 4          ;start of the interrupt handler code
ISR:
     movwf     W_Save              ; Save context
     movf      STATUS,w
     movwf     STATUS_Save

     btfsc     INTCON,T0IF         ;check to ensure there has been timer0 overflow
     goto      ServiceTimer0       ;if overflow, service the interrupt
     goto      ExitISR             ;no interrupt, restore context and return

ServiceTimer0:
     bcf       STATUS,RP0          ;select bank0
     bcf       STATUS,RP1
     bcf       INTCON,T0IF         ;clear the interrupt flag in software

     movfw     PORTD               ;put current state of PORTD into Display1
     movwf     Display1
     decfsz    Delay1,f            ;if 15 interrupts have occurred, then invert Display1
     goto      SkipCom
     comf      Display1,f
     movlw     .15                 ;if 15 interrupts, move 15 back into counter
     movwf     Delay1
SkipCom:                           ;if not yet 15 interrupts, exit handler
     goto      ExitISR

ExitISR:
     movf      STATUS_Save,w       ;restore the save context
     movwf     STATUS
     swapf     W_Save,f            ;use swaps to restore the status
     swapf     W_Save,w
     retfie                        ;return from interrupt

Start:
     bsf       STATUS,RP0          ; select bank1
     movlw     0xFF
     movwf     TRISA               ;PORTA all input
     movlw     0x01
     clrf      TRISD               ;PORTD all output

     movlw     0x00                ; Left Justified, Vdd-Vss referenced
     movwf     ADCON1

     movlw     B'10000111'         ; set prescaler to /256
     movwf     OPTION_REG          

     bsf       STATUS,RP1          ; select bank 3
     movlw     0xFF                ;Port A pins Analog
     movwf     ANSEL
     bcf       STATUS,RP0          ; back to Register Bank 0
     bcf       STATUS,RP1

     movlw     0x41
     movwf     ADCON0         ; configure A2D for Fosc/8, Channel 0 (RA0), and turn on the A2D module
     movlw     0x08
     movwf     Display

     movlw     B'10100000'         ; enable Timer 0 and global interrupts
     movwf     INTCON
     clrf      Display             ;initially clear variables and output
     clrf      PORTD
     clrf      Display1

MainLoop:
    NOP                             ;wait for signal stabilization
    NOP
    NOP
    NOP
    NOP
    BANKSEL     ADCON0
    BSF         ADCON0,1    ;begin ADC
    BTFSC       ADCON0,1    ;loop until ADC is complete
    GOTO        $-1
    MOVFW       ADRESH      ;move the ADRESH into w variable prior to operations
    ANDLW       b'11111110'
    clrf        Display
    MOVWF       Display
    BTFSC       Display1,0
    bsf         Display,0
    movfw       Display
    movwf       PORTD

    goto        MainLoop

    end

